package dk.liljedahl.christian.apx.shipdaemon;

import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.util.StringUtils;

public class IncomingMessageParser {
	static Mediator myMediator;

	public IncomingMessageParser(Mediator mediator){
		IncomingMessageParser.myMediator = mediator;
	}
	
	public void ParseMessage(Message message){
	   	// This is where we process the message 
    	
    	String messageBody = message.getBody();
    	String replyText = "";

        String fromName = StringUtils.parseBareAddress(message.getFrom());

    	// Simple
    	String messagebody = messageBody.toLowerCase().trim();

    	if(messageBody.startsWith("analogread(")) {
    		try {
    			// The format is: analogread(pin)
				// Seems like we are beeing asked for analog data
				String pin = messagebody.replaceAll("analogread\\(", ""); // get 'pin)'
				pin = pin.substring(0, pin.indexOf(")"));  // strip the last )

				int n = Integer.parseInt(pin);
				int analogV = myMediator.arduinoFirmata.analogRead(n);
				
				replyText = "analog(" + n + ")=" + analogV;
			} catch (NumberFormatException e) {
				replyText = "Error: Bad number format in '" + messageBody +"'";
			}
    		
    	} else if(messageBody.startsWith("digitalread(")) {
    		try {
    			// Format: digitalread(pin)
				// Seems like we are beeing asked for digital data
				String pin = messagebody.replaceAll("digitalread\\(", ""); // get 'pin)'
				pin = pin.substring(0, pin.indexOf(")"));  // strip the last )

				int n = Integer.parseInt(pin);
				int digitalV = myMediator.arduinoFirmata.digitalRead(n);
				
				replyText = "digital(" + n + ")=" + digitalV;
			} catch (NumberFormatException e) {
				replyText = "Error: Bad number format in '" + messageBody +"'";
			}
    		
    	} else if(messageBody.startsWith("digitalwrite(")) {
    		try {
    			// The format of a digitalwrite(pin,value) ;
				// Seems like we are beeing asked to write digital data
    			
				String pinvalue = messagebody.replaceAll("digitalwrite\\(", ""); // get 'pin,value)'
				pinvalue = pinvalue.substring(0, pinvalue.indexOf(")"));  // strip the last ) now: 'pin,value'
				String[] pv = pinvalue.split(",");  // split on ,
				if(!pv.equals(null) && pv.length ==2){
					String pin = pv[0];
					String value = pv[1];

					int p = Integer.parseInt(pin);
					int v = Integer.parseInt(value);
					myMediator.arduinoFirmata.digitalWrite(p, v);
					
					replyText = "digital(" + p + ")==" + v;
					
				}

			} catch (NumberFormatException e) {
				replyText = "Error: Bad number format in '" + messageBody +"'";
			}
    		
    	} else {
    		
    		// Run the Expression Parser
    		ExpressionParser expParser = new ExpressionParser();

    		// Get the analog
    		for(int i = 0;i<6;i++){
    			expParser.analog[i] = myMediator.arduinoFirmata.analogRead(i);
    		}

    		// Get the digital
    		for(int i = 0;i<14;i++){
    			// TODO - Intelligence would state to only do checks depending on pinmode
    			expParser.digital[i] = myMediator.arduinoFirmata.digitalRead(i);
    			// Set the digitalwrite to -1 to know if it has been changed
    			expParser.digitalwrite[i] = -1;
    			// Set the analogwrite to -1 to know if it has been changed
    			expParser.analogwrite[i] = -1;
    		}
   		
    		// inject the scriptmemory data to let the script change the memory.
    		// TODO - THis might be a stupid way of coding
    		for(int i = 0;i<30;i++){
    			expParser.scriptmemory_int[i] = myMediator.scriptmemory_int[i];
    		}

    		// Send the incoming message to the script
    		expParser.incoming = messageBody;
    		
    		// Set the name
    		expParser.incomingname[0] = myMediator.xmppmachine.getName(fromName);
    		//TODO understand why we need an String array
        	expParser.response[0] = "";
        	
        	// TODO - yet another silly [0 - this for presence status
        	expParser.status[0] = "";
        	
        	
    		// Get the response

    		// Load them into the ExpressionParser
    		expParser.script = myMediator.responseScript;
    		// Run the expression parser
    		expParser.evaluateResponseScript();

    		// extract the scriptmemory data to save them.
    		for(int i = 0;i<30;i++){
    			myMediator.scriptmemory_int[i] = expParser.scriptmemory_int[i];
    		}

    		// Extract the digitalwrite and analogwrite
    		for(int i = 0;i<14;i++){
    			// Digital write
    			int writevalueDigital = expParser.digitalwrite[i];
    			if(writevalueDigital > -1 && writevalueDigital <=1){
    				// -1 is magic number - Something was changed
    				myMediator.arduinoFirmata.digitalWrite(i, writevalueDigital); 
    			}
    			
    			// Analog write. We hope that firmata keeps track of pwn and don't fuck it up
    			int writevalueAnalog = expParser.analogwrite[i];
    			if(writevalueAnalog > -1 && writevalueAnalog <=255){
    				// -1 is magic number - Something was changed
    				myMediator.arduinoFirmata.analogWrite(i, writevalueAnalog); 
    			}
    		}

    		// Extract status - if != "" then change the presence status 
    		if(!expParser.status[0].equals("")){
    			// We have a status message
    			myMediator.xmppmachine.setStatus(expParser.status[0]);
    		}

    		replyText = expParser.response[0];
    		//replyText = "Error: I do not yet understand ' " + messageBody + "'" + " I know 'analogread(n)' where n is [0-5] and 'digitalread(n)' where n is [0-14] and 'digitalwrite(n)' where n is [0-14]";
    	}
    	
        Message reply = new Message();
        reply.setTo(fromName);
        reply.setType(Message.Type.chat);
        reply.setBody(replyText);
        myMediator.xmppmachine.sendPacket(reply);           		
	}

}
